#include <QCustomPlot/qcustomplot.h>
#include "widgettwo.h"
#include "mytablemodel.h"
#include <eigenhelper.h>
#include "splinefitter.h"
#include "olsfitter.h"
#include <rapidcsv.h>

void WidgetTwo::initControlPanel() {
    MyWidget::initControlPanel();
    QStringList type{u8"y = a*exp(b*x)", u8"一次多项式", u8"二次多项式", u8"三次多项式", u8"四次多项式"};

    m_comboDataType = new QComboBox;
    m_comboDataType->addItems(QStringList{"新增确诊","累计确诊"});
    m_comboDoundary->addItems(type);

    m_spinLeft->setMinimum(0.0);
    m_spinLeft->setMaximum(100.0);
    m_spinLeft->setRange(-1e10, 1e10);
    m_spinLeft->setEnabled(true);
    m_spinRight->setRange(-1e10, 1e10);
    m_spinRight->setEnabled(true);
    m_spinEval->setEnabled(false);

    m_layoutControl->addWidget(new QLabel(u8"拟合公式"), 1, 0);
    m_layoutControl->addWidget(new QLabel(u8"X min"), 2, 0);
    m_layoutControl->addWidget(new QLabel(u8"X max"), 3, 0);
    m_layoutControl->addWidget(new QLabel(u8"新增/累计"), 6, 0);
    m_layoutControl->addWidget(m_comboDataType, 6, 1);
    m_labPerimeter->setText("");

}

void WidgetTwo::loadFile(){
    if (!m_csvFilePath.isEmpty()) {
        rapidcsv::Document doc(m_csvFilePath.toLocal8Bit().toStdString());

        int y1,y2;
        if(m_comboDataType->currentIndex() == 0){
             y1 = doc.GetColumnIdx("newAddConfirm");
             y2 = doc.GetColumnIdx("today_confirm");
        }else{
             y1 = doc.GetColumnIdx("confirm");
             y2 = doc.GetColumnIdx("total_confirm");
        }

        if (y1 == -1 && y2 == -1) {
            QMessageBox::critical(this, "文件存在错误",
                                  QString("无法定位到\"newAddConfirm\"或\"today_confirm\",请修改文件！").arg(m_csvFilePath),
                                  QMessageBox::Ok);
            return;
        }
        auto y = qMax(y1, y2);
        bool ret = m_model1->setFromCsv(m_csvFilePath, 0, y);
        if (!ret) {
            QMessageBox::critical(this, "文件存在错误",
                                  QString("无法打开文件\"%1\"，请检查程序是否有权限读取"
                                          "或者文件内容是否满足规范！").arg(m_csvFilePath),
                                  QMessageBox::Ok);
        } else {
            m_spinLeft->setValue(m_model1->xMin());
            m_spinRight->setValue(m_model1->xMax());
        }
    }
}


void WidgetTwo::connectSingals() {

    MyWidget::connectSingals();

    connect(m_btnOpen, &QPushButton::clicked, [this]() {
        m_csvFilePath = QFileDialog::getOpenFileName(this, "打开数据", ".", "CSV文件 (*.csv);;文本文件 (*.txt)");
        loadFile();
    });

    connect(m_comboDoundary, qOverload<int>(&QComboBox::currentIndexChanged), [this]() {
        setParamater();
        reset();
    });

    connect(m_spinEval,qOverload<double>(&QDoubleSpinBox::valueChanged),[this](double val){
       int day = static_cast<int>(val);
       int maxDay = static_cast<int>(m_model1->xMax());
       if (day>maxDay){
           int cnt = 0;
        for(int i = maxDay+1;i<=day;++i){
            int added =  static_cast<int>(m_abstractFitter[0](i));
            std::cout<<added<<",";
            cnt+=added;
        }
        std::cout<<std::endl;
        m_labPerimeter->setText(QString("%1~%2日累计新增：%3").arg(maxDay).arg(day).arg(cnt));
       }
    });
    connect(m_spinLeft, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &WidgetTwo::reset);
    connect(m_spinRight, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &WidgetTwo::reset);
    connect(m_comboDataType,qOverload<int>(&QComboBox::currentIndexChanged),this,&WidgetTwo::loadFile);

}

QPointF WidgetTwo::fitRange() {
    return {m_spinLeft->value(), m_spinRight->value()};
}

WidgetTwo::WidgetTwo(QWidget *parent)
        : MyWidget(parent) {

//    这几个初始化函数存在依赖关系，不要随便改变顺序
    WidgetTwo::initControlPanel();
    WidgetTwo::initTableView();
    WidgetTwo::initPlotCanvas(2);
    WidgetTwo::connectSingals();

    auto mainLayout = new QGridLayout;
    mainLayout->addWidget(m_tableView, 0, 0, 2, 1);
    mainLayout->addWidget(m_plot, 0, 1);
    mainLayout->addLayout(m_layoutControl, 1, 1);
    mainLayout->setColumnStretch(1, 1);
    mainLayout->setColumnStretch(0, 0);
    setLayout(mainLayout);
    m_abstractFitter = new OLSFitter;
    dynamic_cast<OLSFitter *>(m_abstractFitter)->setExp();
    WidgetTwo::setParamater();
    m_spinEval->setRange(0,100000);
}

WidgetTwo::~WidgetTwo() {
    delete m_abstractFitter;
}

void WidgetTwo::refit(){
    MyWidget::refit();
    m_spinEval->setEnabled(true);
}

void WidgetTwo::setParamater() {
    auto index = m_comboDoundary->currentIndex();
    if (index == 0) {
        dynamic_cast<OLSFitter *>(m_abstractFitter)->setExp();
    } else {
        dynamic_cast<OLSFitter *>(m_abstractFitter)->setPoly(index);
    }

}









